package cn.com.support.authentication;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;

import javax.ejb.EnterpriseBean;

import cn.com.commons.utils.StringUtil;

/**
 * 认证控制工具
 * 
 * @since 2012-3-15 上午12:18:29
 * @version 1.0
 * @author Microbun
 * 
 */
public class AuthenticationUtil {

	private static final char AUTH_DECOLLATOR = ',';

	private static final char TYPE_DECOLLATOR = '&';

	private static final char VALUE_DECOLLATOR = ':';

	private static final String SUPER = "super";

	/**
	 * 创建资源认证码
	 * 
	 * @param num
	 *            资源认证码
	 * @param type
	 *            资源所属类型
	 * @return
	 */
	public static ResourceAuthCode createAuthCode(Long num, String type) {
		return new ResourceAuthCode(num.toString(), type);
	}

	/**
	 * 通过资源认证码构造一个认证码集合
	 * 
	 * @param acc
	 *            认证码集合
	 * @return 认证码集合字符串
	 */
	public static String bulidAuthentication(Collection<ResourceAuthCode> acc) {
		Map<String, List<Long>> authMap = new TreeMap<String, List<Long>>();
		if (acc==null || acc.size()==0){
			return null;
		}
		for (ResourceAuthCode ac : acc) {
			if (ac == null || ac.getType() == null) {
				break;
			}
			List<Long> authlist = authMap.get(ac.getType());
			if (authlist == null) {
				authlist = new ArrayList<Long>();
			}
			if (ac.getAttribute() != null) {
				long postion = Long.parseLong(ac.getAttribute());
				int segment = (int) (postion / 64);
				int offset = (int) (postion % 64);
				segment = (offset == 0 ? segment - 1 : segment);
				offset = (offset == 0 ? 64 : offset);
				if (authlist.size() <= segment) {
					int len = segment - authlist.size() + 1;
					for (int i = 0; i < len; i++) {
						authlist.add(0L);
					}
				}
				Long auth = authlist.get(segment);
				authlist.set(segment, auth | 1L << (offset-1) );
				authMap.put(ac.getType(), authlist);
			}
		}

		// 转化为字符串
		String authentication = null;
		for (Entry<String, List<Long>> entry : authMap.entrySet()) {
			// String.
			if (authentication == null) {
				authentication = entry.getKey() + VALUE_DECOLLATOR
						+ StringUtil.join(entry.getValue(), AUTH_DECOLLATOR);
			} else {
				authentication += TYPE_DECOLLATOR + entry.getKey()
						+ VALUE_DECOLLATOR
						+ StringUtil.join(entry.getValue(), AUTH_DECOLLATOR);
			}
		}
		return authentication;
	}

	/**
	 * 判断资源是否在认证集合中
	 * <p>
	 * 
	 * @param rac
	 *            资源认证码
	 * @param authentication
	 *            认证码集合,如果为值为<code>super</code>永远返回<code>true</code>
	 *            ，认证码集合格式：menu:999,999&action:999,999
	 * @return
	 */
	public static boolean containsResrc(ResourceAuthCode rac,
			String authentication) {
		boolean isContains = false;
		if (rac == null || authentication == null) {
			return isContains;
		}

		// 如果权限码没有指定类型，则表示权限有误
		if (StringUtil.isEmpty(rac.getType())) {
			return isContains;
		}
		// 解析权限集
		String[] auths = authentication.split(TYPE_DECOLLATOR + "");

		// 如果认证码为SUPER，则不进行权限认证
		if (SUPER.equals(authentication)) {
			return true;
		}

		// 权限认证
		for (int i = 0; i < auths.length; i++) {
			if (auths[i].matches(rac.getType() + ".*")) {
				// 将权限集中的权限取出来，然后看权限码所在的二进制位是否为1，如果为1，则表示有权限，否则没有权限
				String ass = auths[i].replaceFirst(rac.getType()
						+ VALUE_DECOLLATOR, "");
				long postion = 0;
				try {
					postion = Long.parseLong(rac.getAttribute());
					int segment = (int) (postion / 64);
					int offset = (int) (postion % 64);
					segment = (offset == 0 ? segment - 1 : segment);
					offset = (offset == 0 ? 64 : offset);
					String[] segmentSet = ass.split(AUTH_DECOLLATOR + "");
					if (segment < segmentSet.length) {
						long auth = Long.parseLong(segmentSet[segment]);
						if ((auth & 1L << offset - 1) != 0) {
							return true;
						}
					}
				} catch (NumberFormatException e) {
					return false;
				}

			}
		}
		return isContains;
	}

	
	public static void main(String[] args) {
		List list=new ArrayList();
		list.add(new ResourceAuthCode("65","mnue"));
		list.add(new ResourceAuthCode("64","mnue"));
		System.out.println(bulidAuthentication(list));
	}
}
